package com.googlecode.bip.xml.export;

import java.io.Closeable;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
import com.googlecode.bip.dao.mysql.MySQLDAOFactory;
import cx.ath.choisnet.sql.ConnectionQuery;

/**
 * TODO: doc
 *
 * @author Claude CHOISNET
 */
//not public
class XMLSurveyConnection
    implements Closeable
{
    private final static Logger logger = Logger.getLogger( XMLSurveyConnection.class );
//    private Connection connection;
//    private ConnectionQuery connectionQuery;

//    //To create a thread local variable
//    static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

//    //To get the connection object in the execute method
//    Connection con = threadLocal.get();

    /**
     * TODO: doc
     *
     * @param sql
     */
    public XMLSurveyConnection()
    {
        //this.connectionPoolManager = DAOFactory.getDAOFactory().getConnectionPoolManager();
        //this.connection = this.connectionPoolManager.getConnectionFromPool();
//        Connection connection = MySQLDAOFactory.getConnection();

        //To set the connection object in the init method
//        threadLocal.set( connection );

//        this.connectionQuery = new ConnectionQuery( connection );
    }

//    /**
//     *
//     * @param sql
//     * @return
//     * @throws SQLException
//     * @throws NamingException
//     */
//    public synchronized ResultSet execute( String sql ) throws SQLException, NamingException
//    {
//        logger.info( "sql = " + sql );
//
//        return connectionQuery.executeQuery( sql );
//    }

    @Override
    public void close() throws IOException
    {
//        try {
//            this.connectionPoolManager.returnConnectionToPool( this.connection );
//            }
//        catch( IllegalArgumentException e ) {
//            logger.fatal( e ); // notify
//            throw e; // propagate exception
//            }
//        catch( SQLException e ) {
//            logger.warn( e ); // notify
//            throw new IOException( "Connection no more valide", e ); // propagate exception
//            }
//        this.connection = null;
    }

    @Override
    protected void finalize() throws Throwable
    {
        try { close(); } catch( IOException ignore ) {}
        super.finalize();
    }

    private Connection getConnection()
        throws NamingException, SQLException
    {
        return MySQLDAOFactory.getConnection();
    }

    protected ResultSetCache executeQuery( String sql, String...rows )
        throws NamingException, SQLException
    {
        Connection      connection  = getConnection();
        ResultSetCache  cache       = new ResultSetCache();

        try {
            ConnectionQuery connectionQuery = new ConnectionQuery( connection ) ;

            ResultSet rset = connectionQuery.executeQuery( sql );

            while( rset.next() ) {
                for( String r:rows ) {
                    cache.put( r, rset.getString( r ) );
                    }
                cache.prepareNext();
                }
            }
        finally {
            connection.close();
            }

        return cache;
    }

//    /**
//    *
//    * @return
//    * @throws SQLException
//    * @throws NamingException
//    */
//   protected ResultSetCache execute(String...rows)
//       throws SQLException, NamingException
//   {
//       logger.info( "sql = " + sql );
//
//       //ResultSet       rset    = connection.executeQuery( sql );
//       ResultSet       rset    = connection.executeQuery( sql );
//       ResultSetCache  cache   = new ResultSetCache();
//
//       while( rset.next() ) {
//           for( String r:rows ) {
//               cache.put( r, rset.getString( r ) );
//               }
//           cache.prepareNext();
//           }
//
//       rset.close();
//
//       return cache;
//   }

    class ResultSetCache
    {
        private List<HashMap<String,String>> cacheMap
            = new ArrayList<HashMap<String,String>>();
        private HashMap<String,String> current;
        private int                    currentIndex = 0;

        private ResultSetCache()
        {
            prepareNext();
        }

        private void prepareNext()
        {
            if( current != null ) {
                cacheMap.add( current );
                }
            current = new HashMap<String,String>();
        }

        public boolean next()
        {
            if( currentIndex < cacheMap.size() ) {
                current = cacheMap.get( currentIndex++ );

                logger.info( "next() = TRUE : currentIndex=" + currentIndex + " - cachesize=" + cacheMap.size() );
                return true;
                }

            return false;
        }

        public void close()
        {
            cacheMap.clear();
            current = null;
            currentIndex = Integer.MAX_VALUE;
        }

        private void put( String columnLabel, String string )
        {
            current.put( columnLabel, string );
            //TestCase.assertTrue( current.containsKey( columnLabel ) );
        }

        public String getString( String columnLabel ) throws SQLException
        {
            if( current.containsKey( columnLabel ) ) {
                return current.get( columnLabel );
                }

            throw new SQLException( "column `" + columnLabel + "` not in cache." );
        }

        public int getInt( String columnLabel ) throws SQLException
        {
            String s = getString( columnLabel );

            if( s == null ) {
                return 0;
                }
            else {
                return Integer.parseInt( s );
                }
        }
    }
}
